import type { App, DirectiveBinding } from 'vue';

/**
 * 防抖指令
 * @directive 按钮防抖指令：v-debounce
 */
interface IElementWithDebounce extends HTMLElement {
	debounceTimer: ReturnType<typeof setTimeout> | null;
	handleClick: () => void;
}

const debounceDirective = (app: App) => {
	app.directive('debounce', {
		mounted(el: IElementWithDebounce, binding: DirectiveBinding) {
			// 传入的不是函数则返回
			if (typeof binding.value !== 'function') return;

			// 判断是否需要立即执行
			const immediate = binding.arg === 'immediate';

			el.debounceTimer = null;

			el.handleClick = () => {
				// 若定时器存在则清除
				if (el.debounceTimer) clearTimeout(el.debounceTimer);

				// 创建新的定时器
				el.debounceTimer = setTimeout(() => {
					binding.value();
				}, Number(import.meta.env.VITE_DELAY));
			};

			// 选择input元素
			const inputElement = el.querySelector('input');
			inputElement ? inputElement.addEventListener('input', el.handleClick) : el.addEventListener('click', el.handleClick);

			// 立即执行
			if (immediate) binding.value();
		},
		beforeUnmount(el: IElementWithDebounce) {
			if (el.debounceTimer) clearTimeout(el.debounceTimer);
			el.debounceTimer = null;
			el.removeEventListener('click', el.handleClick);
		},
	});
};

export default debounceDirective;
